/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Window.java
 *
 * Created on 22/08/2012, 12:34:16 AM
 */
package app.scraper.textyard;

import java.awt.Color;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.table.DefaultTableModel;

import app.scraper.textyard.Scraper.StatusPostable;
import app.scraper.textyard.model.Department;
import app.scraper.textyard.model.Term;

/**
 * 
 * @author Mature Dev Team
 */
public class Window extends javax.swing.JFrame implements StatusPostable {

	/** Creates new form Window */
	public Window() {
		initComponents();
		this.setLocation(350, 300);
		this.setSize(650, 630);
	}

	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
	 * content of this method is always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        chooser = new javax.swing.JFileChooser();
        jLabel1 = new javax.swing.JLabel();
        button_loadpage = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        combo_terms = new javax.swing.JComboBox();
        button_select_schools = new javax.swing.JButton();
        bar = new javax.swing.JProgressBar();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        table_departments = new javax.swing.JTable();
        button_delete_all = new javax.swing.JButton();
        button_select_all = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        box_file = new javax.swing.JTextField();
        button_select = new javax.swing.JButton();
        button_scrape = new javax.swing.JButton();
        bar2 = new javax.swing.JProgressBar();
        jLabel5 = new javax.swing.JLabel();
        combo_schools = new javax.swing.JComboBox();
        button_select_term = new javax.swing.JButton();
        statusLabel = new java.awt.Label();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("TextYard Scraper");
        setBounds(new java.awt.Rectangle(500, 200, 800, 800));
        setMinimumSize(new java.awt.Dimension(750, 700));
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jLabel1.setText("TextYard Book Scraper");
        getContentPane().add(jLabel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 20, -1, -1));

        button_loadpage.setText("Load Page");
        button_loadpage.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_loadpageActionPerformed(evt);
            }
        });
        getContentPane().add(button_loadpage, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 60, -1, -1));

        jLabel2.setText("Select Term:");
        getContentPane().add(jLabel2, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 160, -1, -1));

        combo_terms.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            @Override
			public void propertyChange(final java.beans.PropertyChangeEvent evt) {
                combo_termsPropertyChange(evt);
            }
        });
        getContentPane().add(combo_terms, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 160, 300, -1));

        button_select_schools.setText("Ok");
        button_select_schools.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_select_schoolsActionPerformed(evt);
            }
        });
        getContentPane().add(button_select_schools, new org.netbeans.lib.awtextra.AbsoluteConstraints(480, 120, -1, -1));
        getContentPane().add(bar, new org.netbeans.lib.awtextra.AbsoluteConstraints(346, 60, 330, 20));

        jLabel3.setText("Departments");
        getContentPane().add(jLabel3, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 200, -1, -1));

        dataModel = new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Select", "Department"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Boolean.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                true, false
            };

            @Override
			public Class getColumnClass(final int columnIndex) {
                return types [columnIndex];
            }

            @Override
			public boolean isCellEditable(final int rowIndex, final int columnIndex) {
                return canEdit [columnIndex];
            }
        };
		table_departments.setModel(dataModel);
        jScrollPane3.setViewportView(table_departments);
        table_departments.getColumnModel().getColumn(0).setPreferredWidth(50);
        table_departments.getColumnModel().getColumn(0).setMaxWidth(50);

        getContentPane().add(jScrollPane3, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 220, 620, 270));

        button_delete_all.setText("Delete All");
        button_delete_all.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_delete_allActionPerformed(evt);
            }
        });
        getContentPane().add(button_delete_all, new org.netbeans.lib.awtextra.AbsoluteConstraints(600, 190, -1, -1));

        button_select_all.setText("Select All");
        button_select_all.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_select_allActionPerformed(evt);
            }
        });
        getContentPane().add(button_select_all, new org.netbeans.lib.awtextra.AbsoluteConstraints(520, 190, -1, -1));

        jLabel4.setText("Select output file:");
        getContentPane().add(jLabel4, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 500, -1, -1));
        getContentPane().add(box_file, new org.netbeans.lib.awtextra.AbsoluteConstraints(170, 500, 440, -1));

        button_select.setText("Select");
        button_select.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_selectActionPerformed(evt);
            }
        });
        getContentPane().add(button_select, new org.netbeans.lib.awtextra.AbsoluteConstraints(620, 500, -1, -1));

        button_scrape.setText("Scrape");
        button_scrape.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_scrapeActionPerformed(evt);
            }
        });
        getContentPane().add(button_scrape, new org.netbeans.lib.awtextra.AbsoluteConstraints(310, 530, 160, 40));
        getContentPane().add(bar2, new org.netbeans.lib.awtextra.AbsoluteConstraints(280, 590, 210, 20));

        jLabel5.setText("Select School:");
        getContentPane().add(jLabel5, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 120, -1, -1));

        combo_schools.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                combo_schoolsActionPerformed(evt);
            }
        });
        getContentPane().add(combo_schools, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 120, 300, -1));

        button_select_term.setText("Ok");
        button_select_term.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(final java.awt.event.ActionEvent evt) {
                button_select_termActionPerformed(evt);
            }
        });
        getContentPane().add(button_select_term, new org.netbeans.lib.awtextra.AbsoluteConstraints(480, 160, -1, -1));

        statusLabel.setVisible(false);
        getContentPane().add(statusLabel, new org.netbeans.lib.awtextra.AbsoluteConstraints(278, 20, 400, 30));

        pack();
    }// </editor-fold>//GEN-END:initComponents

	Scraper scraper = null;

	private void button_loadpageActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_loadpageActionPerformed
		statusLabel.setVisible(false);
		enableProgressBar(bar, "Loading Page...");
		combo_terms.removeAllItems();
		combo_schools.removeAllItems();
		dataModel.setRowCount(0);
		scraper = new Scraper();
		scraper.setStatus(this);
		scraper.school = combo_schools;
		scraper.bar = bar;
		scraper.start();
	}// GEN-LAST:event_button_loadpageActionPerformed

	private void button_select_schoolsActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_select_schoolsActionPerformed
		statusLabel.setVisible(false);
		combo_terms.removeAllItems();
		dataModel.setRowCount(0);
		String name = (String) combo_schools.getSelectedItem();
		try {
			List<Term> terms = scraper.loadTermsForSchool(name);
			DefaultComboBoxModel model = (DefaultComboBoxModel) combo_terms.getModel();
			for (Term item : terms) {
				model.addElement(item);
			}
		} catch (Exception ex) {
			Logger.getLogger(Window.class.getName()).log(Level.SEVERE, null, ex);
			postErrorMsg("Server doesn't respond. Please, retry");
			disableProgressBar(bar);
		}
	}// GEN-LAST:event_button_select_schoolsActionPerformed

	// private void combo_termsActionPerformed(java.awt.event.ActionEvent evt)
	private void button_select_termActionPerformed(final java.awt.event.ActionEvent evt) {
		statusLabel.setVisible(false);
		dataModel.setRowCount(0);
		enableProgressBar(bar, "Processing Departments...");
		scraper.bar2 = bar2;
		bar2.setIndeterminate(false);
		bar2.setMinimum(0);
		bar2.setMaximum(100);
		final Term selectedTerm = (Term) combo_terms.getSelectedItem();

		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				try {
					List<Department> depts = scraper.loadDepartmentForTerm(selectedTerm);
					DefaultTableModel model = (DefaultTableModel) table_departments.getModel();

					for (int i = 0; i < depts.size(); i++) {
						model.setNumRows(model.getRowCount() + 1);
						model.setValueAt(depts.get(i), model.getRowCount() - 1, 1);
					}
					disableProgressBar(bar);
					disableProgressBar(bar2);
					setOutputFileName();
				} catch (Exception e) {
					Logger.getLogger(Window.class.getName()).log(Level.SEVERE, null, e);
					postErrorMsg("Server doesn't respond. Please, retry");
					disableProgressBar(bar);
				}
			}
		};
		new Thread(runnable).start();
	}

	private void button_delete_allActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_delete_allActionPerformed
		// TODO add your handling code here:
		DefaultTableModel model = (DefaultTableModel) table_departments.getModel();
		for (int i = 0; i < model.getRowCount(); i++) {
			model.setValueAt(false, i, 0);

		}
		selectionList.clear();
	}// GEN-LAST:event_button_delete_allActionPerformed

	private void button_select_allActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_select_allActionPerformed
		// TODO add your handling code here:
		DefaultTableModel model = (DefaultTableModel) table_departments.getModel();
		for (int i = 0; i < model.getRowCount(); i++) {
			model.setValueAt(true, i, 0);

		}

	}// GEN-LAST:event_button_select_allActionPerformed

	private void button_selectActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_selectActionPerformed
		chooser.showSaveDialog(this);
		File f = chooser.getSelectedFile();
		if (f != null) {
			box_file.setText(f.getAbsolutePath());
		}
	}// GEN-LAST:event_button_selectActionPerformed
		// scrape button

	private void button_scrapeActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_button_scrapeActionPerformed
		final String file = box_file.getText();
		selectionList = new ArrayList<Integer>();
		if (file != null && !file.isEmpty()) {
			for (int i = 0; i < table_departments.getRowCount(); i++) {
				Object valueAt = table_departments.getValueAt(i, 0);
				if (valueAt != null && (Boolean) valueAt) {
					selectionList.add(i);
				}
			}
			scraper.setOutputFile(file);
			scraper.selection = selectionList;

			enableProgressBar(bar, "Scrapping...");
			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						scraper.sendSearchRequest();
						disableProgressBar(bar);
						disableProgressBar(bar2);
					} catch (Exception e) {
						Logger.getLogger(Window.class.getName()).log(Level.SEVERE, null, e);
						ResultsExporter resultExporter = new ResultsExporter(file);
						resultExporter.export(scraper.getResultMap());
						postErrorMsg("Operation completed with an error");
						disableProgressBar(bar);
						disableProgressBar(bar2);
					}
				}

			}).start();

		} else {
			JOptionPane.showMessageDialog(null, "Please, select a file");
		}
	}// GEN-LAST:event_button_scrapeActionPerformed

	private void enableProgressBar(final JProgressBar bar, final String text) {
		bar.setString(text);
		bar.setStringPainted(true);
		bar.setIndeterminate(true);
	}

	private void disableProgressBar(final JProgressBar bar) {
		bar.setString("Done");
		bar.setStringPainted(false);
		bar.setIndeterminate(false);
		bar.setValue(0);
	}

	private void combo_schoolsActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_combo_schoolsActionPerformed
		// TODO add your handling code here:
	}// GEN-LAST:event_combo_schoolsActionPerformed

	private void combo_termsPropertyChange(final java.beans.PropertyChangeEvent evt) {// GEN-FIRST:event_combo_termsPropertyChange

	}// GEN-LAST:event_combo_termsPropertyChange

	private void setOutputFileName() {
		String school = ((String) combo_schools.getSelectedItem()).replaceAll("[\\\\\\s/]", "_");
		String term = ((Term) combo_terms.getSelectedItem()).getTermName().replaceAll("[\\\\\\s/]", "_");
		box_file.setText("C:/" + school + "_" + term + "_result.csv");
	}
	
	
	@Override
	public void postBreaking() {
		statusLabel.setText("Too many retries. Breaking operation.");
		statusLabel.setForeground(Color.BLACK);
		statusLabel.setVisible(true);
	}

	@Override
	public void postPastLimitError() {
		statusLabel.setText("IP blocked after " + scraper.getProcessedClasses() + " book searches.");
		statusLabel.setForeground(Color.RED);
		statusLabel.setVisible(true);
	}

	@Override
	public void postStatusIPBlocked() {
		statusLabel.setText(getTimeoutString(Scraper.BLOCKED_TIMEOUT));
		statusLabel.setForeground(Color.RED);
		statusLabel.setVisible(true);
		
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				for (int i = Scraper.BLOCKED_TIMEOUT - 1; i >= 0; i--) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					statusLabel.setText(getTimeoutString(i));
				}
				statusLabel.setVisible(false);
			}
		}, 0);
	}

	private String getTimeoutString(final int seconds) {
		String secs = String.valueOf(seconds % 60);

		if (secs.equals("0")) {
			secs += "0";
		}
		String result = "IP blocked after searching books for " + scraper.getProcessedClasses()
				+ " classes. Waiting " + seconds / 60 + ":" + secs;
		return result;
	}

	@Override
	public void postProgress(final int val) {
		bar2.setValue(bar2.getValue() + val);
	}

	@Override
	public void postErrorMsg(final String msg) {
		statusLabel.setText(msg);
		statusLabel.setForeground(Color.RED);
		statusLabel.setVisible(true);
	}

	/**
	 * @param args
	 *            the command line arguments
	 */

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JProgressBar bar;
    private javax.swing.JProgressBar bar2;
    private javax.swing.JTextField box_file;
    private javax.swing.JButton button_delete_all;
    private javax.swing.JButton button_loadpage;
    private javax.swing.JButton button_scrape;
    private javax.swing.JButton button_select;
    private javax.swing.JButton button_select_all;
    private javax.swing.JButton button_select_schools;
    private javax.swing.JButton button_select_term;
    private javax.swing.JFileChooser chooser;
    private javax.swing.JComboBox combo_schools;
    private javax.swing.JComboBox combo_terms;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JScrollPane jScrollPane3;
    private java.awt.Label statusLabel;
    private javax.swing.JTable table_departments;
    // End of variables declaration//GEN-END:variables
	private javax.swing.table.DefaultTableModel dataModel;
	private List<Integer> selectionList;

}
